#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>  

#include "global.h"  
#include "room.h"
#include "connections.h"


static struct user_t users[MAX_USERS];

static int count = 0;

static int size_bytes = 0;

/* Adds the new user "nickname" to the room.
 * Returns:
 *			0 - Successful.
 * 			1 - Error: the nickname is already taken.
 * 			2 - Error: the room is full.
*/
int login_user(const char *nickname, int sock_fd)
{
	if (connections_get_status(sock_fd) != CONNECTED) {
		send_unexpected_msg(sock_fd);
		return 1;		
	}

	if (count == MAX_USERS) {
		send_login_error_msg(sock_fd,2);
		return 2;
	}   

	if (user_lookup(nickname) != -1) {
		send_login_error_msg(sock_fd,1);
		return 1;		
	}
	    
	connections_log(sock_fd);
		
	int i;
	for(i = 0; users[i].nick != NULL; i++);
	users[i].nick = (char *) malloc(strlen(nickname)+1);
	strcpy(users[i].nick, nickname);
	users[i].fd = sock_fd;
	size_bytes += strlen(nickname)+1;
	count++;
	
	/* Notifying clients of the event */
	
	send_login_ok_msg(sock_fd);
	fd_set msg_to;
	FD_ZERO(&msg_to);
	connections_get_logged(&msg_to);
	connections_all_but(sock_fd,&msg_to,&msg_to);
	send_user_up_msg(msg_to,nickname);
	
	return 0;
}

/* Removes the user "nickname" from the room.
 * Returns:
 *			0 - Successful.
 *          1 - Unsuccessful. 
*/
int logout_user(const char *nickname)
{
	int i = user_lookup(nickname);
	// printf("logout_user() : look_up=%d\n",i);
	
	if (i==-1)
		return 1;

	/* Notifying clients of the event */  		                         
	int sock = user_nicktosock(nickname);
	connections_close(sock);
	
	fd_set msg_to;
	FD_ZERO(&msg_to);
	connections_get_logged(&msg_to);
	send_user_down_msg(msg_to,nickname);
	
	/* Clear user info from memory */		
	size_bytes -= strlen(users[i].nick)+1;
	free(users[i].nick);
	users[i].fd = 0;
	users[i].nick = NULL;
	// provably replace by bzero(&users[i],sizeof(user_t))
	count--;
                           
	return 0;
}

int logout_user_by_fd(int sock_fd)
{
	int i = user_lookup_by_fd(sock_fd); 
	
	// printf("logout_user() : look_up=%d\n",i);
	
	if (i==-1)
		return 1;
	
	/* Notifying clients of the event */
	connections_close(sock_fd);
	
	fd_set msg_to;
	FD_ZERO(&msg_to);
	connections_get_logged(&msg_to);
	send_user_down_msg(msg_to,user_socktonick(sock_fd));		
	
	/* Clear user info from memory */
	size_bytes -= strlen(users[i].nick)+1;
	free(users[i].nick);
	users[i].fd = 0;
	users[i].nick = NULL;
	// provably replace by bzero(&users[i],sizeof(user_t))
	count--;
	
	return 0;
}

int user_lookup(const char *nick)                    
{
	int i;
	for(i = 0; i < MAX_USERS; i++)
	{
		if (users[i].nick != NULL)
			if (strcmp(users[i].nick,nick) == 0)
				return i;
	}
	return -1;	
}

int user_lookup_by_fd(int sock_fd)                    
{
	int i;
	for(i = 0; i < MAX_USERS; i++)
	{
		if (users[i].nick != NULL)
			if (users[i].fd == sock_fd)
				return i;
	}
	return -1;	
}

char *user_socktonick(int fd)
{
	int r = user_lookup_by_fd(fd);
	return ((r==-1) ? NULL : (users[r].nick));
}

int user_nicktosock(const char *nick)
{
	int r = user_lookup(nick);
	return ((r==-1) ? r : (users[r].fd)); 
}

int room_size_bytes()
{
	return size_bytes;
}

void list_users(char* buffer)
{
	char* x = buffer;
	int i;
	for(i = 0; i < MAX_USERS; i++)
	{
		if (users[i].nick != NULL) {
			memcpy(x,users[i].nick,strlen(users[i].nick));
			x += strlen(users[i].nick);
			*x = '\n';
			x++;		
		}
	}

}

void debug_room()
{
	printf(" ------  room.c - debug_room()  ------ \n");
	printf("users[]:\n");
	int i;
	for(i = 0; i < MAX_USERS; i++)
	{
		printf("\t[%d] : <%s> <fd=%d>\n",i,users[i].nick,users[i].fd);
	}
	printf("\n");
	printf("count : %d\n",count);
	printf("size_bytes : %d\n",size_bytes);
	printf(" ------  end of debug_room()  ------ \n");   
}
